<html><head>
    <meta charset="utf-8">
    <title>HTML5鼠标经过粒子散开动画特效  </title>

    <style>
        html, body {
            position: absolute;
            overflow: hidden;
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background:#000;
            touch-action: none;
            content-zooming: none;
        }
        canvas {
            position: absolute;
            width: 100%;
            height: 100%;
            background:#000;
        }</style>
</head>
<body>
<canvas width="1303" height="843"></canvas>

<script>
    "use strict";
    {
        // particles class
        class Particle {
            constructor(k, i, j) {
                this.i = i;
                this.j = j;
                this.init();
                this.x = this.x0;
                this.y = this.y0;
                this.pos = posArray.subarray(k * 3, k * 3 + 3);
                this.pointer = pointer;
            }
            init() {
                this.x0 = canvas.width * 0.5 + this.i * canvas.width / 240;
                this.y0 = canvas.height * 0.5 + this.j * canvas.height / 160;
            }
            move() {
                const dx = this.pointer.x - this.x;
                const dy = this.pointer.y - this.y;
                const d = Math.sqrt(dx * dx + dy * dy);
                const s = 1000 / d;
                this.x += -s * (dx / d) + (this.x0 - this.x) * 0.02;
                this.y += -s * (dy / d) + (this.y0 - this.y) * 0.02;
                // update buffer position
                this.pos[0] = this.x;
                this.pos[1] = this.y;
                this.pos[2] = 0.15 * s * s;
            }
        }
        // webGL canvas
        const canvas = {
            init(options) {
                // set webGL context
                this.elem = document.querySelector("canvas");
                const gl = (this.gl =
                    this.elem.getContext("webgl", options) ||
                    this.elem.getContext("experimental-webgl", options));
                if (!gl) return false;
                // compile shaders
                const vertexShader = gl.createShader(gl.VERTEX_SHADER);
                gl.shaderSource(
                    vertexShader,
                    `
					precision highp float;
					attribute vec3 aPosition;
					uniform vec2 uResolution;
					void main() {
						gl_PointSize = max(2.0, min(30.0, aPosition.z));
						gl_Position = vec4(
							( aPosition.x / uResolution.x * 2.0) - 1.0,
							(-aPosition.y / uResolution.y * 2.0) + 1.0,
							0.0,
							1.0
						);
					}
      	`
                );
                gl.compileShader(vertexShader);
                const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
                gl.shaderSource(
                    fragmentShader,
                    `
					precision highp float;
					void main() {
						vec2 pc = 2.0 * gl_PointCoord - 1.0;
						gl_FragColor = vec4(1.0, 0.85, 0.25, 1.0 - dot(pc, pc));
					}
				`
                );
                gl.compileShader(fragmentShader);
                const program = (this.program = gl.createProgram());
                gl.attachShader(this.program, vertexShader);
                gl.attachShader(this.program, fragmentShader);
                gl.linkProgram(this.program);
                gl.useProgram(this.program);
                // resolution
                this.uResolution = gl.getUniformLocation(this.program, "uResolution");
                gl.enableVertexAttribArray(this.uResolution);
                // canvas resize
                this.resize();
                window.addEventListener("resize", () => this.resize(), false);
                return gl;
            },
            resize() {
                this.width = this.elem.width = this.elem.offsetWidth;
                this.height = this.elem.height = this.elem.offsetHeight;
                for (const p of particles) p.init();
                this.gl.uniform2f(this.uResolution, this.width, this.height);
                this.gl.viewport(
                    0,
                    0,
                    this.gl.drawingBufferWidth,
                    this.gl.drawingBufferHeight
                );
            }
        };
        const pointer = {
            init(canvas) {
                this.x = 0.1 + canvas.width * 0.5;
                this.y = canvas.height * 0.5;
                this.s = 0;
                ["mousemove", "touchstart", "touchmove"].forEach((event, touch) => {
                    document.addEventListener(
                        event,
                        e => {
                            if (touch) {
                                e.preventDefault();
                                this.x = e.targetTouches[0].clientX;
                                this.y = e.targetTouches[0].clientY;
                            } else {
                                this.x = e.clientX;
                                this.y = e.clientY;
                            }
                        },
                        false
                    );
                });
            }
        };
        // init webGL canvas
        const particles = [];
        const gl = canvas.init({
            alpha: false,
            stencil: true,
            antialias: true,
            depth: false
        });
        // additive blending "lighter"
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
        gl.enable(gl.BLEND);
        // init pointer
        pointer.init(canvas);
        // init particles
        const nParticles = 240 * 80;
        const posArray = new Float32Array(nParticles * 3);
        let k = 0;
        for (let i = -120; i < 120; i++) {
            for (let j = -40; j < 40; j++) {
                particles.push(new Particle(k++, i, j));
            }
        }
        // create position buffer
        const aPosition = gl.getAttribLocation(canvas.program, "aPosition");
        gl.enableVertexAttribArray(aPosition);
        const positionBuffer = gl.createBuffer();
        // draw all particles
        const draw = () => {
            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
            gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);
            gl.bufferData(
                gl.ARRAY_BUFFER,
                posArray,
                gl.DYNAMIC_DRAW
            );
            gl.drawArrays(gl.GL_POINTS, 0, nParticles);
        }
        // main animation loop
        const run = () => {
            requestAnimationFrame(run);
            for (const p of particles) p.move();
            draw();
        };
        requestAnimationFrame(run);
    }
</script>

<div style="text-align:center;margin:50px 0; font:normal 14px/24px 'MicroSoft YaHei';">
    <p>适用浏览器：360、FireFox、Chrome、Opera、傲游、搜狗、世界之窗. 不支持Safari、IE8及以下浏览器。</p>
</div>



</body></html>